package com.itdfq.springbootmongodb.service;

import com.itdfq.springbootmongodb.domain.GeoNear2Document;
import com.itdfq.springbootmongodb.domain.GeoNearDocument;
import com.itdfq.springbootmongodb.domain.StoreBean;
import com.itdfq.springbootmongodb.dto.NearStoreParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GeoNearOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: QianMo
 * @date: 2021/12/23 10:49
 * @mark:
 */
@Service
public class StoreService {

    @Autowired
    private MongoTemplate mongoTemplate;

    //对应的查询sql
    /**
     db.getCollection('store').aggregate([
     {
     $geoNear: {
     near: { type: "Point", coordinates: [ 114.06821, 22.546212 ] },
     distanceField: "dist",
     maxDistance: 200,
     spherical: true
     }
     },
     {
     $skip:0
     }
     ,
     {
     $limit:20
     }
     ])

     aggregate的stage操作符
     常用的stage操作符
     $match: 匹配过滤
     $group: 分组
     $project: 标记输出文档的的字段,_id字段默认输出
     $unwind:将文档中的数组拆分成各个字段
     $skip: 跳过多少字段
     $limit: 限制输出文档数量

     */

    /**
     * 查询附近的门店
     *
     * @param query 条件
     * @param lng   经度
     * @param lat   纬度
     * @param dist  需要过滤距离，不要默认是0
     * @return
     */
    public List<StoreBean> findNear(Query query, double lng, double lat, double dist, Integer page, Integer pageSize) {
        if (query == null) {
            query = new Query();
        }
        List<AggregationOperation> aggregationList = new ArrayList<>();
        //使用了过时的方法
//        aggregationList.add(new GeoNearDocument(query, new Point(lng, lat), dist));
        aggregationList.add(new GeoNear2Document(query, new Point(lng, lat), dist));
        aggregationList.add(Aggregation.skip((long) (page - 1) * pageSize));
        aggregationList.add(Aggregation.limit(pageSize));
        aggregationList.add(Aggregation.sort(Sort.Direction.ASC, "dist"));
        Aggregation agg = Aggregation.newAggregation(
                aggregationList);
        AggregationResults<StoreBean> results = mongoTemplate.aggregate(agg, "storeBean", StoreBean.class);
        return results.getMappedResults();
    }

    public List<StoreBean> findNearStore(NearStoreParam param) {
        //  分页查询	page页码，pageSize每页展示几个
//        Pageable pageable = PageRequest.of(param.getPage() - 1, param.getPageSize(), Sort.by(Sort.Order.desc("dist")));
//        Query query = new Query().with(pageable);
        Query query = new Query();
        Criteria criteria = new Criteria();
        if (!CollectionUtils.isEmpty(param.getStoreIds())) {
            criteria.and("storeId").in(param.getStoreIds());
        }
        if (param.getDist() == null) {
            param.setDist(0);
        }
        if (param.getEnabled() != null) {
            criteria.and("enable").is(param.getEnabled());
        }
        if (param.getAreaCode() != null) {
            criteria.and("area_code").is(param.getAreaCode());
        }
        if (param.getExamineState() != null) {
            criteria.and("examine_state").is(param.getExamineState());
        }
        if (param.getIsPublicAssessment() != null) {
            criteria.and("is_public_assessment").is(param.getIsPublicAssessment());
        }
        if (param.getType() != null) {
            criteria.and("type").is(param.getType());
        }
        query.addCriteria(criteria);
        return findNear(query, param.getLongitude(), param.getLatitude(), param.getDist(), param.getPage(), param.getPageSize());
    }


}
